package com.wis.compress;

import java.util.ArrayList;
import java.util.List;

public class Douglas {
    public List<Point> points = new ArrayList<Point>();
    private static final double D = 1.0/200.0;

    public Douglas(){
    }

    public Douglas(List<Point> source) {
        points = source;
    }

    public void compress(Point pointStart,Point pointEnd){
        /**
         * 假设直线方程为 Ax + By + C = 0
         * 已知两点(x0 , y0),(x1 , y1)，求出直线方程为(y1 - y0)x + (x0 - x1)y + (y0*x1 - y1*x0) = 0;
         * 再依次求出中间各点到直线的距离 d = |( Ax + By + C) / ( A² + B²)|，用二分法找到近似曲线
         * 然后删除满足阈值条件的中间点
         */
        boolean switchvalue = false;
        double A = pointEnd.getY()-pointStart.getY();
        double B = pointStart.getX()-pointEnd.getX();
        double C = pointStart.getY()*pointEnd.getX()-pointEnd.getY()*pointStart.getX();
        double d = 0;
        double dmax = 0;
        int m = points.indexOf(pointStart);
        int n = points.indexOf(pointEnd);
        
        if(n == m + 1){
            return;
        }
        Point pointMiddle = null;
        List<Double> distance = new ArrayList<Double>();
        for(int i = m+1 ; i < n ; i++){
            d = Math.abs(A*(points.get(i).getX())+B*(points.get(i).getY())+C)/Math.sqrt(Math.pow(A,2)+Math.pow(B,2));
            distance.add(d);
        }
        dmax = distance.get(0);
        for(int j = 1 ; j < distance.size() ; j++){
            if(distance.get(j) > dmax){
                dmax = distance.get(j);
            }
        }
        if(dmax>D){
            switchvalue = true;
        }else{
            switchvalue = false;
        }
        if(!switchvalue){
            for(int i = m+1 ; i < n ; i++){
                points.get(i).setIndex(-1);
            }
        }else{
            for(int i = m+1 ; i < n ; i++){
                if(Math.abs(A*(points.get(i).getX())+B*(points.get(i).getY())+C)/Math.sqrt(Math.pow(A,2)+Math.pow(B,2)) == dmax){
                    pointMiddle = points.get(i);
                }
            }
            compress(pointStart,pointMiddle);
            compress(pointMiddle,pointEnd);
        }
    }
}
